package service

import (
	"context"
	"encoding/json"
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"inventory/api/bilinadmin"
	"inventory/api/inventory"
	"inventory/internal/constant"
	"inventory/internal/pkg/region"
	"inventory/pkg/orm"
	"inventory/pkg/util"
	"strconv"
	"time"

	"inventory/internal/model"
	"inventory/pkg/ecode"
	"inventory/pkg/log"
)

// GetWarehouseList 获取仓库列表
func (s *Service) GetWarehouseList(ctx context.Context, req *inventory.GetWarehouseListRequest) (resp *inventory.GetWarehouseListReply, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	var (
		total      int64
		warehouses []*model.Warehouse
		views      []*inventory.WarehouseView
	)
	logger := log.FromContext(ctx)
	if total, warehouses, err = s.dao.FindWarehouses(ctx, sgId, req.PStoreId, int(req.PageNo), int(req.PageSize)); err != nil {
		logger.Errorf("获取仓库列表失败: %v", err)
		return
	}
	views = make([]*inventory.WarehouseView, len(warehouses))
	for i, w := range warehouses {
		views[i] = &inventory.WarehouseView{
			Id:              w.ID,
			Name:            w.Name,
			StoreId:         w.StoreID,
			Address:         w.Address,
			PickUp:          w.PickUp,
			CityExpress:     w.CityExpress,
			OrdinaryExpress: w.OrdinaryExpress,
			Latitude:        w.Lat,
			Longitude:       w.Lng,
			CityCode:        w.CityCode,
			RegionCode:      w.RegionCode,
			Contact:         w.Contact,
			Mobile:          w.Mobile,
			Deadline:        w.Deadline.String(),
			StorageMode:     uint32(w.StorageMode),
		}
	}
	resp = &inventory.GetWarehouseListReply{
		Total:      uint64(total),
		Warehouses: views,
	}
	return
}

// GetWarehouseDetail 获取仓库详情
func (s *Service) GetWarehouseDetail(ctx context.Context, req *inventory.CommonObjectRequest) (view *inventory.WarehouseView, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	var warehouse *model.Warehouse
	if warehouse, err = s.dao.GetWarehouseInfo(ctx, sgId, req.PStoreId, req.Id); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = constant.ErrWarehouseNotExist
		}
		return
	}
	view = &inventory.WarehouseView{
		Id:              warehouse.ID,
		StoreId:         warehouse.StoreID,
		Name:            warehouse.Name,
		Address:         warehouse.Address,
		Latitude:        warehouse.Lat,
		Longitude:       warehouse.Lng,
		CityCode:        warehouse.CityCode,
		RegionCode:      warehouse.RegionCode,
		Contact:         warehouse.Contact,
		Mobile:          warehouse.Mobile,
		PickUp:          warehouse.PickUp,
		CityExpress:     warehouse.CityExpress,
		OrdinaryExpress: warehouse.OrdinaryExpress,
		Deadline:        warehouse.Deadline.String(),
		StorageMode:     uint32(warehouse.StorageMode),
	}
	return
}

// AddWarehouse 新增仓库
func (s *Service) AddWarehouse(ctx context.Context, req *inventory.AddWarehouseRequest) (
	resp *inventory.AddWarehouseReply, err error) {
	var warehouse *model.Warehouse
	empId, sgId := req.WebToken.EmpId, req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	now := time.Now()
	deadline := util.Duration{}
	if err = deadline.Scan(req.Deadline); err != nil {
		err = ecode.BadRequest("截止下单时间格式不合法: %s", req.Deadline)
		return
	}
	warehouse = &model.Warehouse{
		SgID:            sgId,
		Name:            req.Name,
		StoreID:         req.StoreId,
		Status:          constant.WarehouseEnable,
		Address:         req.Address,
		CityCode:        uint32(req.CityCode),
		RegionCode:      req.RegionCode,
		Lat:             req.Latitude,
		Lng:             req.Longitude,
		Contact:         req.Contact,
		Mobile:          req.Mobile,
		PickUp:          req.PickUp,
		CityExpress:     req.CityExpress,
		OrdinaryExpress: req.OrdinaryExpress,
		Deadline:        deadline,
		StorageMode:     uint8(req.StorageMode),
		Operator:        empId,
		CreateTime:      now,
		UpdateTime:      now,
	}
	if req.StoreId > 0 || req.PStoreId > 0 {
		var storeInfo *bilinadmin.StoreInfoReply
		if req.StoreId == 0 {
			// 门店模式直接读p_store_id, store_id允许前端传0
			req.StoreId = req.PStoreId
			warehouse.StoreID = req.PStoreId
		} else if req.PStoreId != 0 && req.PStoreId != req.StoreId {
			err = constant.ErrPermissionError
			return
		}
		if storeInfo, err = s.downstream.GetStoreInfo(ctx, req.WebToken.SgId, req.StoreId); err != nil {
			return
		}
		cityCode, _ := strconv.Atoi(storeInfo.DistrictCode)
		if storeInfo.Address == "" || storeInfo.Latitude == 0 || storeInfo.Longitude == 0 || cityCode == 0 || storeInfo.RegionCode == "" {
			err = ecode.BadRequest("所选门店未配置完善，无法创建仓库，请返回门店配置页面在地图选择门店地址保存后再试")
			return
		}
		warehouse.Name = storeInfo.StoreName
		warehouse.Contact = storeInfo.ContactName
		warehouse.Mobile = storeInfo.ContactMobile
		warehouse.Address = storeInfo.Address
		warehouse.Lat = storeInfo.Latitude
		warehouse.Lng = storeInfo.Longitude
		if !region.CheckCityCode(cityCode) {
			err = ecode.BadRequest("城市编码错误：%d", cityCode)
			return
		}
		warehouse.CityCode = uint32(cityCode)
		warehouse.RegionCode = storeInfo.RegionCode
	}
	err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		if req.StoreId != 0 {
			var existRecord *model.Warehouse
			if existRecord, err = s.dao.GetWarehouseInfoByStoreID(ctx, req.StoreId); err != nil {
				if errors.Cause(err) == gorm.ErrRecordNotFound {
					if err = s.dao.Create(ctx, warehouse); err != nil {
						return
					}
				} else {
					return
				}
			} else if existRecord.Status == constant.WarehouseDeleted {
				warehouse.ID = existRecord.ID
				if err = s.dao.Save(ctx, warehouse); err != nil {
					return
				}
			} else {
				err = ecode.BadRequest("门店只允许创建一个关联仓库")
				return
			}
		} else {
			if _, err = s.dao.GetWarehouseInfoByName(ctx, sgId, req.Name); err != nil {
				if errors.Cause(err) == gorm.ErrRecordNotFound {
					if err = s.dao.Create(ctx, warehouse); err != nil {
						return
					}
				} else {
					return
				}
			} else {
				err = constant.ErrDuplicateInput
				return
			}
		}
		warehouseUpdatePayload, _ := json.Marshal(&inventory.WarehouseUpdatePayload{
			Id:              warehouse.ID,
			Name:            warehouse.Name,
			Address:         warehouse.Address,
			Latitude:        warehouse.Lat,
			Longitude:       warehouse.Lng,
			CityCode:        warehouse.CityCode,
			RegionCode:      warehouse.RegionCode,
			Contact:         warehouse.Contact,
			Mobile:          warehouse.Mobile,
			PickUp:          warehouse.PickUp,
			CityExpress:     warehouse.CityExpress,
			OrdinaryExpress: warehouse.OrdinaryExpress,
			Deadline:        warehouse.Deadline.String(),
			StorageMode:     uint32(warehouse.StorageMode),
			Source:          req.Source,
			SgId:            sgId,
			Timestamp:       warehouse.UpdateTime.Unix(),
		})
		if err = s.dao.PublishRepeatedNSQMessage(
			ctx, constant.TopicWarehouseUpdate, strconv.Itoa(int(warehouse.ID)), warehouseUpdatePayload); err != nil {
			return err
		}
		resp = &inventory.AddWarehouseReply{
			Id:      warehouse.ID,
			Message: "SUCCESS",
		}
		return
	})
	if err != nil {
		return
	}
	return
}

// EditWarehouse 编辑仓库
func (s *Service) EditWarehouse(ctx context.Context, req *inventory.EditWarehouseRequest) (
	resp *inventory.DefaultResp, err error) {
	var (
		warehouse  *model.Warehouse
		// needNotify = false
	)
	empId, sgId := req.WebToken.EmpId, req.WebToken.SgId
	deadline := util.Duration{}
	if err = deadline.Scan(req.Deadline); err != nil {
		err = ecode.BadRequest("截止下单时间格式不合法: %s", req.Deadline)
		return
	}
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		if warehouse, err = s.dao.LockWarehouse(ctx, req.Id, sgId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = constant.ErrWarehouseNotExist
			}
			return
		} else if warehouse.Status == constant.WarehouseDeleted || (req.PStoreId != 0 && req.PStoreId != warehouse.StoreID) {
			err = constant.ErrWarehouseNotExist
			return
		}
		if warehouse.Deadline != deadline {
			// 截止接单时间修改时，需要检查是否有“待取货”履约单，存在时不允许修改
			var processOrders []*model.ProcessOrder
			if processOrders, err = s.dao.FindUnfinishedPickupProcessOrders(ctx, req.Id); err != nil {
				return
			}
			if len(processOrders) != 0 {
				err = ecode.AppendMessage(constant.ErrForbiddenAction, "当前仓库存在待自提履约单，不允许修改截止时间")
				return
			}
		}
		if warehouse.StorageMode != uint8(req.StorageMode) {
			if err = s.dao.UpdateBomStorageMode(ctx, warehouse.ID, uint8(req.StorageMode)); err != nil {
				return
			}
			// if warehouse.StoreID != 0 {
			// 	needNotify = true
			// }
		}
		if warehouse.Name != req.Name {
			// 同名检查
			if _, err = s.dao.GetWarehouseInfoByName(ctx, sgId, req.Name); err != nil {
				if errors.Cause(err) != gorm.ErrRecordNotFound {
					return
				}
			} else {
				err = constant.ErrDuplicateInput
				return
			}
		}
		warehouse.Contact = req.Contact
		warehouse.Mobile = req.Mobile
		warehouse.PickUp = req.PickUp
		warehouse.CityExpress = req.CityExpress
		warehouse.OrdinaryExpress = req.OrdinaryExpress
		warehouse.Deadline = deadline
		warehouse.Operator = empId
		warehouse.StorageMode = uint8(req.StorageMode)
		warehouse.UpdateTime = time.Now()
		warehouse.Name = req.Name
		warehouse.Address = req.Address
		warehouse.CityCode = uint32(req.CityCode)
		warehouse.RegionCode = req.RegionCode
		warehouse.Lat = req.Latitude
		warehouse.Lng = req.Longitude
		if err = s.dao.Save(ctx, warehouse); err != nil {
			return
		}
		//warehouseUpdatePayload, _ := json.Marshal(&inventory.WarehouseUpdatePayload{
		//	Id:              warehouse.ID,
		//	Name:            warehouse.Name,
		//	Address:         warehouse.Address,
		//	Latitude:        warehouse.Lat,
		//	Longitude:       warehouse.Lng,
		//	CityCode:        warehouse.CityCode,
		//	RegionCode:      warehouse.RegionCode,
		//	Contact:         warehouse.Contact,
		//	Mobile:          warehouse.Mobile,
		//	PickUp:          warehouse.PickUp,
		//	CityExpress:     warehouse.CityExpress,
		//	OrdinaryExpress: warehouse.OrdinaryExpress,
		//	Deadline:        warehouse.Deadline.String(),
		//	StorageMode:     uint32(warehouse.StorageMode),
		//	Source:          req.Source,
		//	SgId:            sgId,
		//	Timestamp:       warehouse.UpdateTime.Unix(),
		//})
		//if err = s.dao.PublishRepeatedNSQMessage(
		//	ctx, constant.TopicWarehouseUpdate, strconv.Itoa(int(warehouse.ID)), warehouseUpdatePayload); err != nil {
		//	return err
		//}
		resp = &inventory.DefaultResp{Status: true}
		return
	})
	return
}

// GetWarehouseCityExpresses  获取同城配送列表
func (s *Service) GetWarehouseCityExpresses(ctx context.Context, req *inventory.CommonPaginateRequest) (
	resp *inventory.GetExpressListReply, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	var (
		total int64
		views []*inventory.ExpressView
	)
	if total, views, err = s.dao.FindWarehouseCityExpresses(ctx, sgId, req); err != nil {
		return
	}
	resp = &inventory.GetExpressListReply{
		Total:      uint32(total),
		Warehouses: views,
	}
	return
}

// GetWarehouseCityExpressPlatform 查看指定仓库同城配送平台列表
func (s *Service) GetWarehouseCityExpressPlatform(ctx context.Context, req *inventory.CommonObjectRequest) (
	resp *inventory.GetCityExpressPlatformReply, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	logger := log.FromContext(ctx)
	var views []*inventory.WarehouseCityExpressPlatformView
	if views, err = s.dao.FindWarehouseCityExpressPlatform(ctx, sgId, req); err != nil {
		logger.Errorf("获取指定仓库同城配送平台列表失败: %v", err)
		return
	}

	resp = &inventory.GetCityExpressPlatformReply{
		Platforms: views,
	}
	return
}

// EditCityExpressConfig 绑定/编辑配送平台信息(主动配置)
func (s *Service) EditCityExpressConfig(ctx context.Context, req *inventory.EditCityExpressPlatformRequest) (resp *inventory.DefaultResp, err error) {
	empId, sgId := req.WebToken.EmpId, req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	resp = &inventory.DefaultResp{Status: true}
	err = s.dao.Transaction(ctx, func(ctx context.Context) error {
		logger := log.FromContext(ctx)
		var config *model.ExpressConfig
		if config, err = s.dao.LockExpressConfigByMode(ctx, sgId, req.Id, req.PlatformId,
			constant.ExpressPlatformModeInitiative); err != nil {
			if !(errors.Cause(err) == gorm.ErrRecordNotFound) {
				logger.Errorf("锁定配送平台配置失败: %w", err)
				return err
			}
			config = &model.ExpressConfig{
				WarehouseID: req.Id,
				PlatformID:  req.PlatformId,
				SgID:        sgId,
				CreateTime:  time.Now(),
			}
		}
		if req.PlatformId == constant.ExpressDada {
			return ecode.BadRequest("达达平台不支持自助配置，请联系客服配置")
		}
		config.Info = req.Info
		config.Operator = empId
		config.UpdateTime = time.Now()
		config.Status = constant.ExpressConfigured
		if err = s.dao.SaveExpressConfig(ctx, config); err != nil {
			return err
		}
		return err
	})
	return
}

// UnbindCityExpressConfig 解绑配送平台信息
func (s *Service) UnbindCityExpressConfig(ctx context.Context, req *inventory.DeleteCityExpressPlatformRequest) (
	resp *inventory.DefaultResp, err error) {
	empId, sgId := req.WebToken.EmpId, req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	resp = &inventory.DefaultResp{
		Status: true,
	}
	err = s.dao.Transaction(ctx, func(ctx context.Context) error {
		logger := log.FromContext(ctx)
		var config *model.ExpressConfig
		if config, err = s.dao.LockExpressConfigByMode(ctx, sgId, req.Id, req.PlatformId,
			constant.ExpressPlatformModeInitiative); err != nil {
			logger.Errorf("锁定配送平台配置失败: %w", err)
			return err
		}
		if req.PlatformId == constant.ExpressDada {
			return ecode.BadRequest("达达平台不支持自助解绑，请联系客服操作")
		}
		config.Operator = empId
		config.Status = constant.ExpressUnbound
		config.UpdateTime = time.Now()
		if err = s.dao.SaveExpressConfig(ctx, config); err != nil {
			return err
		}
		return err
	})
	return
}

// GetCityExpressRegions 查看同城配送区域
func (s *Service) GetCityExpressRegions(ctx context.Context, req *inventory.CommonObjectRequest) (
	resp *inventory.GetCityExpressRegionsResponse, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	logger := log.FromContext(ctx)
	var warehouse *model.Warehouse
	if warehouse, err = s.dao.GetWarehouseInfo(ctx, sgId, req.PStoreId, req.Id); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = constant.ErrWarehouseNotExist
		}
		return
	}
	var regions []*model.ExpressCoordinates
	if regions, err = s.dao.FindWarehouseExpressCoordinates(ctx, warehouse.ID); err != nil {
		logger.Errorf("锁定配送平台配置失败: %w", err)
		return
	}
	views := make([]*inventory.CityExpressRegionView, len(regions))
	for i, r := range regions {
		views[i] = &inventory.CityExpressRegionView{
			StartingFee: r.ShippingFee,
			ShippingFee: r.ShippingFee,
			Coordinates: json.RawMessage(r.Coordinates),
			Status:      r.Status,
			CityCode:    r.CityCode,
		}
	}
	resp = &inventory.GetCityExpressRegionsResponse{
		Latitude:  warehouse.Lat,
		Longitude: warehouse.Lng,
		Regions:   views,
	}
	return
}

// GetWarehouseOrdinaryExpressRegions 获取仓库普通配送区域 && 平台
func (s *Service) GetWarehouseOrdinaryExpressRegions(ctx context.Context, req *inventory.CommonObjectRequest) (resp *inventory.GetOrdinaryRegionsReply, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	var warehouse *model.Warehouse
	if warehouse, err = s.dao.GetWarehouseInfo(ctx, sgId, req.PStoreId, req.Id); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = constant.ErrWarehouseNotExist
		}
		return
	}
	var expressCities []*model.ExpressCity
	if expressCities, err = s.dao.FindWarehousesExpressCities(ctx, warehouse.ID); err != nil {
		return
	}
	var platforms []*inventory.PlatformView
	if platforms, err = s.dao.FindWarehousesPlatforms(ctx, warehouse.ID, uint8(inventory.DeliverType_ORDINARY)); err != nil {
		return
	}

	regions := make([]*inventory.OrdinaryExpressRegionView, len(expressCities))
	for i, c := range expressCities {
		cities := make([]uint32, len(c.CityCodes))
		for j, cityCode := range c.CityCodes {
			cities[j] = uint32(cityCode)
		}
		regions[i] = &inventory.OrdinaryExpressRegionView{
			FirstWeightPrice:      c.FirstWeightPrice,
			AdditionalWeightPrice: c.AdditionalWeightPrice,
			Cities:                cities,
		}
	}
	resp = &inventory.GetOrdinaryRegionsReply{
		Regions:   regions,
		Platforms: platforms,
	}
	return
}

// EditWarehouseCityExpressRegions 编辑同城配送区域
func (s *Service) EditWarehouseCityExpressRegions(ctx context.Context, req *inventory.EditWarehouseCityExpressRegionsRequest) (resp *inventory.DefaultResp, err error) {
	empId, sgId := req.WebToken.EmpId, req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	for _, r := range req.Regions {
		if !region.CheckCityCode(int(r.CityCode)) {
			err = ecode.BadRequest("城市编码错误：%d", r.CityCode)
			return
		}
	}
	resp = &inventory.DefaultResp{Status: true}
	err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		var warehouse *model.Warehouse
		if warehouse, err = s.dao.GetWarehouseInfo(ctx, sgId, req.PStoreId, req.Id); err != nil {
			return
		}
		if err = s.dao.DeleteAllExpressCoordinatesByWarehouseID(ctx, warehouse.ID); err != nil {
			return
		}
		now := time.Now()
		for i, r := range req.Regions {
			if err = s.dao.AddWarehouseExpressCoordinates(ctx, &model.ExpressCoordinates{
				WarehouseID: warehouse.ID,
				Index:       uint32(i),
				SgID:        warehouse.SgID,
				StartingFee: r.StartingFee,
				ShippingFee: r.ShippingFee,
				CityCode:    r.CityCode,
				Coordinates: orm.JSON(r.Coordinates),
				Operator:    empId,
				Status:      true,
				CreateTime:  now,
				UpdateTime:  now,
			}); err != nil {
				return
			}
		}
		return
	})
	return
}

// GetOrdinaryExpressList 仓库普通快递列表
func (s *Service) GetOrdinaryExpressList(ctx context.Context, req *inventory.CommonPaginateRequest) (resp *inventory.GetExpressListReply, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	var (
		total int64
		views []*inventory.ExpressView
	)
	if total, views, err = s.dao.FindWarehouseOrdinaryExpress(ctx, sgId, req); err != nil {
		return
	}
	resp = &inventory.GetExpressListReply{
		Total:      uint32(total),
		Warehouses: views,
	}
	return
}

// EditWarehouseOrdinaryExpressRegions  编辑普通快递配送区域
func (s *Service) EditWarehouseOrdinaryExpressRegions(ctx context.Context, req *inventory.EditOrdinaryExpressRegionsRequest) (
	resp *inventory.DefaultResp, err error) {
	// region之间城市编码不允许重复
	empId, sgId := req.WebToken.EmpId, req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	existCityMap := util.IntBoolMap{}
	for _, reqRegion := range req.Regions {
		for _, cityCode := range reqRegion.Cities {
			if !region.CheckCityCode(int(cityCode)) {
				err = ecode.BadRequest("城市编码错误：%d", cityCode)
				return
			}
			if _, ok := existCityMap[int(cityCode)]; ok {
				err = ecode.BadRequest("城市[%s]重复出现在多个区域", region.Regions(int(cityCode)))
				return
			}
			existCityMap[int(cityCode)] = true
		}
	}
	resp = &inventory.DefaultResp{
		Status: true,
	}
	err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		var (
			AllowPlatformIDS []int
			warehouse        *model.Warehouse
		)
		AllowPlatformIDS, err = s.dao.FindPlatformIDsByMode(ctx, int(inventory.DeliverType_ORDINARY))
		platformMap := make(util.IntBoolMap)
		for _, i := range AllowPlatformIDS {
			platformMap[i] = true
		}
		for _, p := range req.Platforms {
			if _, ok := platformMap[int(p)]; !ok {
				return ecode.BadRequest("非法的平台ID")
			}
		}
		if warehouse, err = s.dao.GetWarehouseInfo(ctx, sgId, req.PStoreId, req.Id); err != nil {
			return
		}
		if err = s.dao.DeleteAllExpressCity(ctx, warehouse.ID); err != nil {
			return
		}
		now := time.Now()
		for i, r := range req.Regions {
			cities := make(orm.IntArray, len(r.Cities))
			for j, cityCode := range r.Cities {
				cities[j] = int(cityCode)
			}
			if err = s.dao.AddWarehouseExpressCity(ctx, &model.ExpressCity{
				WarehouseID:           warehouse.ID,
				Index:                 uint32(i),
				SgID:                  sgId,
				FirstWeightPrice:      r.FirstWeightPrice,
				AdditionalWeightPrice: r.AdditionalWeightPrice,
				CityCodes:             cities,
				Operator:              empId,
				CreateTime:            now,
				UpdateTime:            now,
			}); err != nil {
				return
			}
		}
		for _, p := range req.Platforms {
			if err = s.dao.AddWarehouseExpressPlatform(ctx, &model.ExpressConfig{
				WarehouseID: warehouse.ID,
				PlatformID:  p,
				SgID:        sgId,
				Status:      constant.ExpressConfigured,
				Operator:    empId,
				CreateTime:  now,
				UpdateTime:  now,
			}); err != nil {
				return
			}
		}
		return
	})
	return
}

// GetWarehouseExpressPlatforms 获取仓库下指定模式平台列表
func (s *Service) GetWarehouseExpressPlatforms(ctx context.Context, req *inventory.GetWarehouseExpressPlatformsRequest) (resp *inventory.GetPlatformsResponse, err error) {
	sgId := req.WebToken.SgId
	if err = s.downstream.CheckAdmin(ctx, req.WebToken, req.PStoreId); err != nil {
		return
	}
	var warehouse *model.Warehouse
	if warehouse, err = s.dao.GetWarehouseInfo(ctx, sgId, req.PStoreId, req.Id); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = constant.ErrWarehouseNotExist
		}
		return
	}
	var platforms []*inventory.PlatformView
	if platforms, err = s.dao.FindWarehousesPlatforms(ctx, warehouse.ID, uint8(req.DeliverType)); err != nil {
		return
	}
	resp = &inventory.GetPlatformsResponse{
		Platforms: platforms,
	}
	return
}

// GetWarehouseAddressInfo 查看仓库地址（退货申请同意时）
func (s *Service) GetWarehouseAddressInfo(ctx context.Context, req *inventory.GetWarehouseAddressInfoRequest) (reply *inventory.GetWarehouseAddressInfoReply, err error) {
	var warehouse *model.Warehouse
	if warehouse, err = s.dao.GetWarehouseInfo(ctx, req.SgId, req.PStoreId, req.Id); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = constant.ErrWarehouseNotExist
		}
		return
	}
	reply = &inventory.GetWarehouseAddressInfoReply{
		StoreId: warehouse.StoreID,
		Name:    warehouse.Name,
		AddressInfo: &inventory.AddressInfo{
			Lat:      warehouse.Lat,
			Lng:      warehouse.Lng,
			CityCode: strconv.Itoa(int(warehouse.CityCode)),
			Contact:  warehouse.Contact,
			Mobile:   warehouse.Mobile,
			Address:  warehouse.Address,
		},
	}
	return
}
